#include "test_cabstractthread_functional.h"

using namespace PILO::Core::String;


INT32 case_CAbstractThread_CreateThread_Basic(void* param);
INT32 case_CAbstractThread_CreateAndKillThread(void* param);
INT32 case_CAbstractThread_CreateAndKillDetachedThread(void* param);

static case_testing_t g_cases[] = {
    {1, "CreateThread                                      ",  0,case_CAbstractThread_CreateThread_Basic, -1},
    {2, "CreateAndKillThread                               ",  0,case_CAbstractThread_CreateAndKillThread, -1},
    {3, "CreateAndKillDetachedThread                       ",  0,case_CAbstractThread_CreateAndKillDetachedThread, -1},


};


INT32 case_CAbstractThread_CreateThread_Basic( void* )
{
    MyThread* thr = new MyThread;
    INT32 rc;    

    int i;
    for (i=0; i<100; i++) {

        thr->setValue(0);

        if (EC_OK!=thr->startThread())
        {
            return -1;
        }

        if (thr->isDetached()) {
            return -3;
        }

        if (thr->state() == EnumStateFinished) {
            return -4;
        }

        rc = thr->waitThread();
        if (rc != EC_OK) {
            return -5;
        }

        if (thr->state() != EnumStateFinishedAndJoined) {
            return -6;
        }

        if (thr->isDetached()) {
            return -8;
        }

        INT32 result = -99;
        rc = thr->getResult(result);
        if (rc!= EC_OK) {
            return -9;
        }

        if (result != 99999)
        {
            return -10;
        }
    }
   
    if (100 != i)
    {
        return -999;
    }

    MyThreadQuickTask qTask;
    for (i=0; i<50; i++) {
        
        qTask.startThread();
        CAbstractThread::sleep(1);
        if (qTask.state() != EnumStateFinished) {
            return -100;
        }
        if (qTask.state() != EnumStateFinished) {
            return -110;
        }
        rc = qTask.waitThread();
        if (rc != EC_OK) {
            return -120;
        }

        INT32 res;
        rc = qTask.getResult(res);
        if (rc != EC_OK) {
            return -130;
        }
        if (res != 7675) {
            return -140;
        }

    }

    return 0;
}

INT32 case_CAbstractThread_CreateAndKillThread(void* )
{
    MyThreadSlowTask *thr = new MyThreadSlowTask;
    INT32 rc; 

    int i=0;
    for (i=0; i<100; i++)
    {
        thr->setValue(0);

        if (EC_OK!=thr->startThread())
        {
            return -1;
        }

        if (thr->isDetached()) {
            return -3;
        }

        if (thr->state() == EnumStateFinished) {
            return -4;
        }

        rc = thr->killThread();
        if (rc != EC_OK)
        {
            return -8;
        }


        rc = thr->waitThread();
        if (ERRCODE(rc) != EC_THREAD_ABORTED) {
            return -5;
        }

        if (thr->state() != EnumStateAbortedAndJoined) {
            return -122;
        }

        if (thr->postKilledCalled != 1) {
            return -6;
        }

        if (thr->preKilledCalled != 1) {
            return -7;
        }
    }

    MyThreadSlowTask qTask;
    for (i=0; i<50; i++) {

        qTask.startThread();
        if (qTask.state() != EnumStatePreparing) {
            return -100;
        }

        rc = qTask.killThread();
        if (rc != EC_OK) {
            return -121;
        }

        if (qTask.state() != EnumStateAborted) {
            return -122;
        }

        rc = qTask.waitThread();
        if (rc != EC_THREAD_ABORTED) {
            return -130;
        }

        if (qTask.state() != EnumStateAbortedAndJoined) {
            return -122;
        }

        if (qTask.postKilledCalled != 1) {
            return -160;
        }

        if (qTask.preKilledCalled != 1) {
            return -170;
        }

        
    }
    
    if ( i != 50) {
        return -999;
    }

    MyThreadQuickTask qTask1;
    for (i=0; i<50; i++) {

        qTask1.startThread();
        if (qTask1.state() != EnumStatePreparing) {
            return -100;
        }

        CAbstractThread::sleep(1);

        if (qTask1.state() != EnumStateFinished) {
            return -112;
        }

        rc = qTask1.killThread();
        if (rc != EC_THREAD_STATE_ERROR) {
            return -121;
        }

        if (qTask1.state() != EnumStateFinished) {
            return -124;
        }

        rc = qTask1.waitThread();
        if (rc != EC_OK) {
            return -130;
        }

        if (qTask1.state() != EnumStateFinishedAndJoined) {
            return -132;
        }

        if (qTask1.finshed != TRUE) {
            return -160;
        }
        INT32 res;
        rc = qTask1.getResult(res);
        if (rc != EC_OK) {
            return -180;
        }
        if (res != 7675) {
            return -190;
        }
    }

    if ( i != 50) {
        return -999;
    }

    return 0;
}



INT32 case_CAbstractThread_CreateAndKillDetachedThread( void* )
{
    MyThreadSlowTask *thr = new MyThreadSlowTask;
    INT32 rc; 

    int i;
    for (i=0; i<100; i++) {
        thr->setValue(0);

        thr->setThreadCreationDetachedState(TRUE);

        if (EC_OK!=thr->startThread())
        {
            return -10;
        }

        if (!thr->isDetached()) {
            return -30;
        }


        if (thr->killThread() != EC_OK)
        {
            return -50;
        }

        if (thr->state() != EnumStateAborted) {
            return -60;
        }

        rc = thr->waitThread();
        if (ERRCODE(rc) != EC_NONSENSE_OPERATION) {
            return -70;
        }

        if (thr->state() != EnumStateAborted) {
            return -80;
        }

        if (thr->postKilledCalled != 1) {
            return -90;
        }

        if (thr->preKilledCalled != 1) {
            return -100;
        }

        INT32 res;
        rc = thr->getResult(res);
        if (rc != EC_THREAD_ABORTED) {
            return -110;
        }

    }
    

    MyThreadQuickTask *qt = new MyThreadQuickTask;
    for (i=0; i<10; i++) {
        qt->setValue(0);

        qt->setThreadCreationDetachedState(TRUE);

        if (EC_OK!=qt->startThread())
        {
            return -210;
        }

        if (!qt->isDetached()) {
            return -230;
        }

        CAbstractThread::sleep(1);

        if (qt->state() != EnumStateFinished) {
            return -240;
        }

        if (qt->killThread() != EC_THREAD_STATE_ERROR)
        {
            return -250;
        }

        if (qt->state() != EnumStateFinished) {
            return -260;
        }

        rc = qt->waitThread();
        if (ERRCODE(rc) != EC_NONSENSE_OPERATION) {
            return -270;
        }

        if (qt->state() != EnumStateFinished) {
            return -280;
        }

        if (qt->finshed != TRUE) {
            return -290;
        }

        INT32 res;
        rc = qt->getResult(res);
        if (rc != EC_OK) {
            return -300;
        }

        if (res != 7675) {
            return -310;
        }

    }



    return 0;
}





static INT32 g_id = 0;

INT32 test_CAbstractThread_Functional(INT32 id, int breakOnErrorOccured)
{
    g_id = id;

    FormatOutputToConsole("Testing Part_%d <cabstractthreadfunctional.h/cpp>\n", id);

    int i=0;
    for (i=0; i<MCF_COUNT_OF(g_cases); i++) {
        case_testing_t * caseParam = &g_cases[i];
        ASSERT(caseParam != NULL);
        FormatOutputToConsole(" #[%03d.%03d]: Testing %s",g_id, caseParam->ct_id, caseParam->ct_decription);

        caseParam->ct_result = caseParam->ct_function(static_cast<case_testing_t *>(caseParam));
        if (caseParam->ct_result == 0) { //ok 
            FormatOutputToConsole("[PASSED]\n");
        } else {
            FormatOutputToConsole("[FAILED:%d]\n",caseParam->ct_result);
            if (breakOnErrorOccured) {
                ASSERT(false);
            }
        }
    }


    FormatOutputToConsole("Result of Part_%d <cabstractthreadfunctional.h/cpp> total %d,   failed %d\n\n",id, MCF_COUNT_OF(g_cases), failedOFCases(g_cases,MCF_COUNT_OF(g_cases) ));
    return 0;
}



// my thread implementation
INT32 MyThread::onRun()
{
    for (int i=0; i<20000000; i++) {
        this->incValue();
    }    

    if (this->value() != 20000000){
        return -1;
    }
    return 99999;
}



INT32 MyThreadSlowTask::onRun()
{
    for (int i=0; i<2000000000; i++) {
        //CAbstractThread::sleep(1);
     
        this->incValue();
    } 

    if (this->value() != 2000000000){
        return -1;
    }
    return 99999;
}

INT32 MyThreadQuickTask::onRun()
{
    _finished = TRUE;
    return 7675;
}
